package com.youzan.cloud.service.impl;

import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.youzan.cloud.common.constant.TokenConstant;
import com.youzan.cloud.common.dto.AccessToken;
import com.youzan.cloud.common.dto.AuthorizationDto;
import com.youzan.cloud.common.exception.AuthenticationFailExcetion;
import com.youzan.cloud.dataobject.ComponentConfig;
import com.youzan.cloud.dataobject.SignatureConfig;
import com.youzan.cloud.mapper.ComponentConfigMapper;
import com.youzan.cloud.mapper.SignatureConfigMapper;
import com.youzan.cloud.service.TokenService;
import com.youzan.cloud.utils.RedisUtil;
import com.youzan.cloud.utils.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author tangsen233
 * @version 1.0
 * @description: token管理
 * @date 2021/12/13 17:50
 */
@Service
@Slf4j
public class TokenServiceImpl implements TokenService {

    @Autowired
    RedisUtil redisUtil;

    @Resource
    SignatureConfigMapper signatureConfigMapper;
    @Resource
    ComponentConfigMapper componentConfigMapper;

    @Override
    public AccessToken getToken(AuthorizationDto authorizationDto) {
        if (StringUtils.isBlank(authorizationDto.getApp_id())) {
            throw new AuthenticationFailExcetion("app_id不得为空");
        }
        if (StringUtils.isBlank(authorizationDto.getApp_secret())) {
            throw new AuthenticationFailExcetion("app_secret不得为空");
        }
        SignatureConfig signatureConfig = signatureConfigMapper.selectConfigByAppIdAndSecret(authorizationDto.getApp_id(), authorizationDto.getApp_secret());
        if (ObjectUtils.isEmpty(signatureConfig)) {
            throw new AuthenticationFailExcetion("未找到对应密钥");
        }
        AccessToken accessToken = new AccessToken();
        //生成token
        StringBuffer sb = new StringBuffer();
        String key = TokenConstant.TOKEN_PREFIX + signatureConfig.getAppId();
        if (StringUtils.isNotBlank(redisUtil.get(key))) {
            return getAccessToken(key, signatureConfig.getAppId());
        }
        ComponentConfig componentConfig = componentConfigMapper.selectBySchema(TokenConstant.COMPONENT_SCHEMA);
        if (Objects.isNull(componentConfig) || StringUtils.isBlank(componentConfig.getConfig())) {
            throw new AuthenticationFailExcetion("配置项为空");
        }
        JSONObject jsonObject = JSONUtil.parseObj(componentConfig.getConfig());
        String content = sb.append(signatureConfig.getAppId()).append(signatureConfig.getAppSecret()).append(UUID.randomUUID()).toString();
        String token = SignUtil.encryptSHA256Hmac(content, signatureConfig.getAppSecret());
        redisUtil.setEx(key, token, jsonObject.getLong("timeout"), TimeUnit.SECONDS);
        accessToken.setAccess_token(token);
        accessToken.setApp_id(signatureConfig.getAppId());
        accessToken.setExpires_in(redisUtil.getExpire(key));
        return getAccessToken(key, signatureConfig.getAppId());
    }

    public AccessToken getAccessToken(String key, String appId) {
        AccessToken accessToken = new AccessToken();
        accessToken.setAccess_token(redisUtil.get(key));
        accessToken.setApp_id(appId);
        accessToken.setExpires_in(redisUtil.getExpire(key));
        return accessToken;
    }

}